<!-- 代码已包含 CSS：使用 TailwindCSS , 安装 TailwindCSS 后方可看到布局样式效果 -->
<template>
  <div class="page-container">
    <!-- 粒子背景 -->
    <div ref="particleContainer" class="particle-container"></div>
    <!-- 登录表单容器 -->
    <div :class="['login-container', { 'shake-animation': showError }]">
      <!-- 头部标题 -->
      <div class="header">
        <h1>欢迎回来</h1>
        <p>请登录您的账户</p>
      </div>
      <!-- 登录表单 -->
      <form @submit.prevent="handleLogin" class="login-form">
        <!-- 用户名输入框 -->
        <div class="input-group">
          <input type="text" v-model="form.username" :class="['input-field', { error: errors.username }]"
            placeholder="请输入用户名" @focus="handleFocus('username')" @blur="handleBlur('username')" />
          <SvgIcon class="fa" :name="'login/SVG-5'" :style="{ color: '#fff' }" />
        </div>
        <!-- 密码输入框 -->
        <div class="input-group">
          <input :type="showPassword ? 'text' : 'password'" v-model="form.password"
            :class="['input-field', { error: errors.password }]" placeholder="请输入密码" @focus="handleFocus('password')"
            @blur="handleBlur('password')" />
          <SvgIcon :class="['fa cursor-pointer', showPassword ? 'fa-eye-slash' : '']" :style="{ color: '#fff' }" :name="'login/SVG-4'"
            @click="togglePassword" />
        </div>
        <!-- 记住密码和忘记密码 -->
        <div class="form-options">
          <label class="remember-me">
            <input type="checkbox" v-model="form.remember" />
            <span>记住我</span>
          </label>
          <a href="#" class="forgot-password">忘记密码？</a>
        </div>
        <!-- 登录按钮 -->
        <button type="submit" :class="[
          'login-button !rounded-button whitespace-nowrap',
          { loading: isLoading },
        ]" :disabled="isLoading">
          <span v-if="!isLoading">登 录</span>
          <SvgIcon v-else class="fa rate" :name="'login/loader'" />
        </button>
        <!-- 其他登录方式 -->
        <div class="other-login cursor-pointer">
          <p>没有账号去注册？</p>
          <div class="social-links">
            <a href="#" class="social-icon">
              <SvgIcon class="fa" :name="'login/SVG'" />
            </a>
            <a href="#" class="social-icon">
              <SvgIcon class="fa" :name="'login/SVG-2'" />
            </a>
            <a href="#" class="social-icon">
              <SvgIcon class="fa" :name="'login/SVG-3'" />
            </a>
          </div>
        </div>
      </form>
      <!-- 错误提示 -->
      <div v-if="errorMessage" class="error-message">
        <i class="fas fa-exclamation-circle mr-2"></i>
        {{ errorMessage }}
      </div>
    </div>
  </div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from "vue";
import axios from "axios";
import { useRouter } from "vue-router";
import { login } from "@/api/login"; //解决引入.ts文件报错方法就是去掉后缀名.ts
import { ElMessage } from "element-plus";
import { useUserStore } from "@/store/user";
import { } from "pinia"
const user = useUserStore();
const { setUserInfo } =user;
const router = useRouter();
const form = ref({
  username: "我是vip",
  password: "123456",
  remember: false,
});

const errors = ref({
  username: false,
  password: false,
});

const isLoading = ref(false);
const showPassword = ref(false);
const showError = ref(false);
const errorMessage = ref("");
const particles = ref([]);
const mouse = ref({ x: 0, y: 0 });
const particleContainer = ref(null);
let animationFrame = null;

const initParticles = () => {
  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d");
  particleContainer.value.appendChild(canvas);

  const resize = () => {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
  };
  resize();

  // 创建粒子
  for (let i = 0; i < 100; i++) {
    particles.value.push({
      x: Math.random() * canvas.width,
      y: Math.random() * canvas.height,
      radius: Math.random() * 2 + 1,
      vx: Math.random() * 2 - 1,
      vy: Math.random() * 2 - 1,
    });
  }

  const animate = () => {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    particles.value.forEach((particle) => {
      particle.x += particle.vx;
      particle.y += particle.vy;
      if (particle.x < 0 || particle.x > canvas.width) particle.vx *= -1;
      if (particle.y < 0 || particle.y > canvas.height) particle.vy *= -1;
      ctx.beginPath();
      ctx.arc(particle.x, particle.y, particle.radius, 0, Math.PI * 2);
      ctx.fillStyle = "rgba(255, 255, 255, 0.5)";
      ctx.fill();

      // 鼠标交互
      const dx = mouse.value.x - particle.x;
      const dy = mouse.value.y - particle.y;
      const distance = Math.sqrt(dx * dx + dy * dy);
      if (distance < 100) {
        const angle = Math.atan2(dy, dx);
        particle.vx = Math.cos(angle) * 0.5;
        particle.vy = Math.sin(angle) * 0.5;
      }
    });
    animationFrame = requestAnimationFrame(animate);
  };
  animate();
};

const handleMouseMove = (e) => {
  mouse.value.x = e.clientX;
  mouse.value.y = e.clientY;
};

const handleResize = () => {
  if (particleContainer.value) {
    const canvas = particleContainer.value.querySelector("canvas");
    if (canvas) {
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
    }
  }
};

const handleLogin = async () => {
  if (isLoading.value) {
    return;
  }
  if (!form.value.username || !form.value.password) {
    showError.value = true;
    errorMessage.value = "请填写完整的登录信息";
    setTimeout(() => {
      showError.value = false;
    }, 500);
    return;
  }
  isLoading.value = true;
  try {
    const res = await login({
      userName: form.value.username,
      userPassword: form.value.password,
      errorMsg: false,
    });
    setUserInfo(res);
    console.log(res);
    errorMessage.value = "";
    router.replace("/");
  } catch (error) {
    showError.value = true;
    errorMessage.value = "用户名或密码错误";
    setTimeout(() => {
      showError.value = false;
    }, 500);
  } finally {
    isLoading.value = false;
  }
};

const handleFocus = (field) => {
  errors.value[field] = false;
  errorMessage.value = "";
};

const handleBlur = (field) => {
  errors.value[field] = !form.value[field];
};

const togglePassword = () => {
  showPassword.value = !showPassword.value;
};

onMounted(() => {
  function postApi() {
    axios
      .get("/bokeefront/login").then((res) => {
        console.log(res,"--------");
      }).catch((res) => {
        console.log(res,"ppppppppp");
      });
  }
  postApi();
  initParticles();
  window.addEventListener("mousemove", handleMouseMove);
  window.addEventListener("resize", handleResize);
});

onBeforeUnmount(() => {
  window.removeEventListener("mousemove", handleMouseMove);
  window.removeEventListener("resize", handleResize);
  if (animationFrame) {
    cancelAnimationFrame(animationFrame);
  }
});
</script>
<style lang="scss" scoped>
.page-container {
  position: relative;
  min-height: 100vh;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: linear-gradient(to bottom right, #3b82f6, #9333ea);
}

.particle-container {
  position: absolute;
  inset: 0;
}

.login-container {
  position: relative;
  z-index: 10;
  background: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(16px);
  border-radius: 1rem;
  padding: 2rem;
  width: 420px;
  animation: slideIn 0.6s ease-out;
}

.header {
  text-align: center;
  margin-bottom: 2rem;
  color: #fff;
}

.header h1 {
  font-size: 1.875rem;
  font-weight: bold;
  color: white;
  margin-bottom: 0.5rem;
}

.header p {
  color: rgb(229, 231, 235);
}

.login-form {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

/* 定义动画 */
@keyframes rotate360 {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

.rate {
  animation: rotate360 2s linear infinite;
}

.input-group {
  position: relative;

  .fa {
    position: absolute;
    right: 0.5rem;
    top: calc(50% - 8px);
    z-index: 1;
  }

  .fa-eye-slash::after {
    width: 2px;
    height: 20px;
    transform: rotate(-45deg);
    text-align: center;
    line-height: 16px;
    position: absolute;
    z-index: 2;
    right: calc(50% - 1px);
    top: calc(50% - 10px);
    background-color: #e8f0fe;
    content: "";
  }
}

.input-field {
  width: 100%;
  padding: 0.75rem 2rem 0.75rem 1rem;
  background: rgba(255, 255, 255, 0.2);
  border: 2px solid transparent;
  color: white;
  border-radius: 0.5rem;
  outline: none;
  transition: all 0.3s;
}

.input-field::placeholder {
  color: rgba(255, 255, 255, 0.7);
}

.input-field.error {
  border-color: #ef4444;
}

.input-group i {
  position: absolute;
  right: 1rem;
  top: 50%;
  transform: translateY(-50%);
  color: rgba(255, 255, 255, 0.7);
}

.toggle-password {
  cursor: pointer;
}

.form-options {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 0.875rem;
  color: rgba(255, 255, 255, 0.8);
}

.remember-me {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
}

.remember-me input[type="checkbox"] {
  border-radius: 0.25rem;
  border-color: rgb(209, 213, 219);
}

.forgot-password {
  transition: color 0.3s;
}

.forgot-password:hover {
  color: white;
}

.login-button {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  padding: 0.75rem;
  border-radius: 0.5rem;
  color: white;
  font-weight: 500;
  transition: all 0.3s;
  transform-origin: center;
}

.login-button:not(.loading) {
  background-color: #2563eb;
}

.login-button:not(.loading):hover {
  background-color: #1d4ed8;
  transform: scale(1.02);
}

.login-button:not(.loading):active {
  transform: scale(0.98);
}

.login-button.loading {
  background-color: rgb(107, 114, 128);
}

.other-login {
  margin-top: 1.5rem;
  text-align: center;
}

.other-login p {
  color: rgba(255, 255, 255, 0.8);
  margin-bottom: 1rem;
}

.social-links {
  display: flex;
  justify-content: center;
  gap: 1rem;
}

.social-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.1);
  transition: all 0.3s ease;
}

.social-icon:hover {
  background: rgba(255, 255, 255, 0.2);
  transform: translateY(-2px);
}

.error-message {
  position: absolute;
  top: -60px;
  left: 50%;
  transform: translateX(-50%);
  background-color: rgba(239, 68, 68, 0.9);
  color: white;
  padding: 12px 24px;
  border-radius: 8px;
  animation: slideDown 0.3s ease-out;
}

.shake-animation {
  animation: shake 0.5s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
}

@keyframes slideIn {
  from {
    opacity: 0;
    transform: translateY(20px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes slideDown {
  from {
    opacity: 0;
    transform: translate(-50%, -20px);
  }

  to {
    opacity: 1;
    transform: translate(-50%, 0);
  }
}

@keyframes shake {

  10%,
  90% {
    transform: translate3d(-1px, 0, 0);
  }

  20%,
  80% {
    transform: translate3d(2px, 0, 0);
  }

  30%,
  50%,
  70% {
    transform: translate3d(-4px, 0, 0);
  }

  40%,
  60% {
    transform: translate3d(4px, 0, 0);
  }
}
</style>
